package geneticpolyimage;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Class Individual represent an individual of the population
 * 
 * @author igor & mattia
 */
public class Individual implements Cloneable {

    public Polygon[] polygons = null;
    public int howmanypoly;
    public double fitness;
    public int width;
    public int height;
    public int vertices;

    /**
     * Generate random individual
     *
     * @param how number of polygons
     * @param numvertices number of verticies per polygon
     * @param maxx width of target image
     * @param maxy height of target image
     */
    public Individual(int how, int numvertices, int maxx, int maxy) {
        width = maxx;
        height = maxy;
        vertices = numvertices;
        this.howmanypoly = how;
        this.polygons = new Polygon[how];
        for (int i = 0; i < this.howmanypoly; i++) {
            polygons[i] = new Polygon(numvertices, maxx, maxy);
        }
    }

    /**
     * Generate individual with specified chormosome
     *
     * @param poly array of polygons
     * @param numvertices number of verticies per polygon
     * @param maxx width of target image
     * @param maxy height of target image
     */
    public Individual(Polygon[] poly, int numvertices, int maxx, int maxy) {
        width = maxx;
        height = maxy;
        vertices = numvertices;
        this.howmanypoly = poly.length;
        this.polygons = poly;
    }

    /**
     * Compute fitness of the individual
     *
     * @param problem   problem for fitness calculation
     * @return fitness of individual
     */
    public double fitness(Problem problem) {
        double distance = problem.verify(this);
        this.fitness = distance;
        return fitness;
    }

    /**
     * Return the chromosome of the individual
     *
     * @return chormosome
     */
    public Polygon[] getPolygons() {
        return this.polygons;
    }

    /**
     * Return a BufferedImage generated by chromosome of the individual
     * @return image of the individual
     */
    public BufferedImage getImage() {
        BufferedImage imagetotest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D localgraphics = (Graphics2D) imagetotest.getGraphics();
        localgraphics.fillRect(0, 0, width, height);
        for (int i = 0; i < polygons.length; i++) {
            Color c = new Color(polygons[i].redvalue, polygons[i].greenvalue, polygons[i].bluevalue, polygons[i].alpha);
            localgraphics.setColor(c);
            localgraphics.fillPolygon(polygons[i].xvertices, polygons[i].yvertices, vertices);
        }
        return imagetotest;
    }

    /**
     * Mutate an attribute of the individual
     */
    public void mutate() {
        Random r = new Random();
        int i = r.nextInt(howmanypoly);

        switch (r.nextInt(5 + vertices)) {
            case 1:
                polygons[i].alpha = r.nextInt(255);
                break;
            case 2:
                polygons[i].redvalue = r.nextInt(255);
                break;
            case 3:
                polygons[i].greenvalue = r.nextInt(255);
                break;
            case 4:
                polygons[i].bluevalue = r.nextInt(255);
                break;
            case 5:
                Polygon temp = polygons[i];
                polygons[i]=polygons[howmanypoly-1];
                polygons[howmanypoly-1]=temp;
                break;
            default:
                int j = r.nextInt(vertices);
                polygons[i].xvertices[j] = r.nextInt(width);
                polygons[i].yvertices[j] = r.nextInt(height);
                break;
        }
    }

    @Override
    /**
     * Override the clone method to colne the polygon array
     */
    public Object clone() {
        try {
            Individual temp = (Individual) super.clone();
            temp.polygons = polygons.clone();
            for (int i = 0; i < howmanypoly; i++) {
                temp.polygons[i] = (Polygon) polygons[i].clone();
            }
            return temp;
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(Individual.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
}
